--[[
-- Author:      feilong
-- DateTime:    2018-04-23 17:19:33
-- Description:

--]]

local socket = require "skynet.socket"
local httpd = require "http.httpd"
local sockethelper = require "http.sockethelper"
local urllib = require "http.url"
local cjson = require "cjson"

---------------------------------------------------------
-- class
---------------------------------------------------------
local Service = class("Service")

function Service:ctor(name)
	--根目录
	local src_path = g.getenv("root")
	local server_name = g.getenv("server_name")
	self.web_root = src_path..server_name.."/view/X-admin/"

	self.handler = new("agent.handler")
	self:register()
end

function Service:register()
	g.dispatch:register('start', handler(self, self.onStart))
	g.dispatch:register('close', handler(self, self.onClose))
	g.dispatch:register('accept', handler(self, self.onAccept))

end

function Service:onStart()

	return true
end

function Service:onClose()

	g.exit()
	return true
end



--接收客户端消息
function Service:onAccept(id, ... )
	socket.start(id)
	-- limit request body size to 8192 (you can pass nil to unlimit)
	local code, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), nil)
	--print("onAccept:",code, url,method, header, body)
	--print(method, header, body )
	if code then
		if code ~= 200 then
			--请求失败
			self:response(id, code)
			socket.close(id)
			return
		else
			local path, query = urllib.parse(url) --解析url
			print("parse(url):", path, query)
			--默认页
			if url == "/" then
				path = "index.html"
			end
			--静态页面
			if self:isStaticFile(path) then
				self:openStaticFile(id,path)
				socket.close(id)
				return
			end
			----------- 需要动态处理的消息-----------
			local token = header.token
			local cmd = path:match(".*%/(.+)$")
			local param
			if query then
				--解析参数
				param = urllib.parse_query(query) or {}
				for k, v in pairs(param) do
					if type(v)=='string' then
						local ok, res = pcall(cjson.decode, v)
						if ok and type(res)=="table" then
							param[k] = res
						else
							param[k] = v
						end
					end
				end
			end
			print("cmd:",cmd, param)
			if string.upper(method)=='POST' then
				--post 方式上传数据
				-- param['post'] = body
				param = urllib.parse_query(body) or {}
				for k, v in pairs(param) do
					if type(v)=='string' then
						param[k]=v
					end
				end
			end
			print("____param___",cmd, param)
			assert(cmd, "http cmd is null")
			self:dispatchClientMessage(id, cmd, param)
		end
	else
		--发生错误
		if url == sockethelper.socket_error then
			g.log:error("socket closed")
		else
			g.log:error(url)
		end
	end
	socket.close(id)
end

--派发客户端消息，对返回消息处理
function Service:dispatchClientMessage(id, cmd, ... )
	local header = {}
	header["Content-Type"] = "application/json"
	local res = g.dispatch:dispatchMessage(_, _, cmd, ...)
	-- print("dispatchClientMessage:",id,res)
	if res and next(res) then
		local error_msg = g.error_code:getDes(res.error_code)
		if error_msg then
			res.error_msg = error_msg
		end
		self:response(id, 200, cjson.encode(res), header)
		return
	end

	local error_msg = cjson.encode({error_code=-1,error_msg="消息无处理"})
	self:response(id, 200, error_msg, header)
end


--返回消息给客户端
function Service:response(id, ...)
	local ok, err = httpd.write_response(sockethelper.writefunc(id), ...)
	if not ok then
		-- if err == sockethelper.socket_error , that means socket closed.
		g.log:error(string.format("fd = %d, %s", id, err))
	end
end

-- 是静态网页文件
function Service:isStaticFile(path)
	local suffix = path:match("^.+(%.%a+)$")
	-- print("___suffix__",suffix)
	if not suffix or suffix==".lua" then
		return false
	end
	return true
end

-- 把静态文件返回给客户端
function Service:openStaticFile(id, file_path)
	local file_path = self.web_root..file_path
	local file = io.open(file_path, "rb")
	if not file then
		return self:response(id, 501, "file not exist!")
	end
	local size = file:seek("end")
	local header = {}
	header["Content-Length"] = size
	file:seek("set", 0)
	local data = file:read("*a")
	file:close()
	self:response(id, 200, data, header)
end

return Service
